package com.joolun.cloud.common.data.tenant;

import cn.hutool.core.util.StrUtil;
import com.joolun.cloud.common.core.constant.CacheConstants;
import com.joolun.cloud.common.core.constant.CommonConstants;
import com.joolun.cloud.common.core.constant.SecurityConstants;
import com.joolun.cloud.common.security.entity.BaseUser;
import com.joolun.cloud.upms.common.dto.UserInfo;
import com.joolun.cloud.upms.common.feign.FeignUserService;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * @author
 */
@Slf4j
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
@AllArgsConstructor
public class TenantContextHolderFilter extends GenericFilterBean {

	private final RedisTemplate redisTemplate;
	private final FeignUserService feignUserService;

	@Override
	@SneakyThrows
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;
		//需要token验权的请求，header中有token，通过token找租户ID
		String authorization = request.getHeader(CommonConstants.AUTHORIZATION);
		if(StrUtil.isNotBlank(authorization) && authorization.contains(OAuth2AccessToken.BEARER_TYPE)){
			String tokenValue = authorization.replace(OAuth2AccessToken.BEARER_TYPE, StrUtil.EMPTY).trim();
			String key = StrUtil.concat(false,SecurityConstants.BASE_PREFIX,SecurityConstants.OAUTH_PREFIX,"access:",tokenValue);
			OAuth2AccessToken oAuth2AccessToken = (OAuth2AccessToken) redisTemplate.opsForValue().get(key);
			if(oAuth2AccessToken != null){
				Map<String, Object> additionalInformation =  oAuth2AccessToken.getAdditionalInformation();
				String tenantId = StrUtil.toString(additionalInformation.get(SecurityConstants.DETAILS_TENANT_ID));
				String switchTenantId = request.getHeader(SecurityConstants.SWITCH_TENANT_ID);
				if(StrUtil.isNotEmpty(switchTenantId)
						&& StrUtil.equals(CommonConstants.USER_TYPE_S, StrUtil.toString(additionalInformation.get(SecurityConstants.DETAILS_TYPE)))
						&& StrUtil.equals(CommonConstants.SYSTEM_TENANT_ID, tenantId)){
					String userName = StrUtil.toString(additionalInformation.get(SecurityConstants.DETAILS_USERNAME));
					String key2 = StrUtil.concat(false, CacheConstants.USER_CACHE, "::", userName);
					BaseUser baseUser = (BaseUser) redisTemplate.opsForValue().get(key2);
					List<String> listTenantIds;
					if(baseUser != null){
						listTenantIds = baseUser.getTenantIds();
					}else{
						UserInfo userInfo = feignUserService.info(userName, SecurityConstants.FROM_IN).getData();
						listTenantIds = userInfo.getSysUser().getTenantIds();
					}
					if(listTenantIds.contains(switchTenantId)){
						//系统管理员类型用户且该切换的租户ID已和此用户绑定，则设置成Header中指定的租户ID
						tenantId = switchTenantId;
					}
				}
				if (StrUtil.isNotBlank(tenantId)) {
					TenantContextHolder.setTenantId(tenantId);
				}
			}
		}else{
			//不需要token验权的请求，header中无token，用header中的租户ID
			String tenantId = request.getHeader(CommonConstants.TENANT_ID);
			if (StrUtil.isNotBlank(tenantId)) {
				TenantContextHolder.setTenantId(tenantId);
			}
		}

		filterChain.doFilter(request, response);
		TenantContextHolder.clear();
	}
}
